package com.bootdo.common.utils.encryptionUtil;

import com.bootdo.common.utils.encryptionUtil.Seal.bytearray;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.sql.Timestamp;

import static com.bootdo.common.utils.encryptionUtil.Seal.BUFFER_SIZE;
import static com.bootdo.common.utils.encryptionUtil.Seal.InitEncryptKey;


public class Header
{
    Seal seal = new Seal();
    Seal.seal_ctx sc = seal.new seal_ctx();

    public static final int CIPHER_HEDER_SIZE = 1024;
    public static final int MAX_CIPHER_MAIN_FLAG = 32;
    public static final int MAX_KEY_INFO = 16;

    public static bytearray gConstCipherFlagBuffer = null;

    PCIPHER_HEADER header = null;

    public PCIPHER_HEADER BuildCipherHeader()
    {
        InitEncryptKey(seal, sc);

        gConstCipherFlagBuffer = seal.new bytearray(MAX_CIPHER_MAIN_FLAG);
        gConstCipherFlagBuffer.a = new byte[]
                {
                        (byte) 0x6E, (byte) 0x7e, (byte) 0x5a, (byte) 0x6d, (byte) 0x00, (byte) 0x89, (byte) 0xDA, (byte) 0x16,
                        (byte) 0xE3, (byte) 0xB3, (byte) 0x51, (byte) 0xEA, (byte) 0x53, (byte) 0xAA, (byte) 0xFB, (byte) 0x8B,
                        (byte) 0xF6, (byte) 0x65, (byte) 0xEF, (byte) 0x5a, (byte) 0xa6, (byte) 0x62, (byte) 0xA0, (byte) 0x87,
                        (byte) 0x65, (byte) 0xF6, (byte) 0x4E, (byte) 0x62, (byte) 0x75, (byte) 0x00, (byte) 0x67, (byte) 0x5C
                };

        //PCIPHER_HEADER header = null;
        long ftTempTime;
        int dwRetVal = 0x00;
        Timestamp stUTC, stLocal;
        header = new PCIPHER_HEADER();

        /**
         * ----------！----------！注意！----------！----------
         * 这里的a不能直接等于，会让MainFlag.a和FlagEncData.a变成同一个变量
         * 应该采用循环的方法赋值
         */
        header.MainFlag = seal.new bytearray(MAX_CIPHER_MAIN_FLAG);
        //header.MainFlag.a=gConstCipherFlagBuffer.a;//这样写会出错
        for (int i = 0; i < MAX_CIPHER_MAIN_FLAG; i++)
        {
            header.MainFlag.a[i] = gConstCipherFlagBuffer.a[i];
        }


        dwRetVal = MAX_CIPHER_MAIN_FLAG;
        header.FlagEncData = seal.new bytearray(MAX_CIPHER_MAIN_FLAG);
        //header.FlagEncData.a = gConstCipherFlagBuffer.a;
        for (int i = 0; i < MAX_CIPHER_MAIN_FLAG; i++)
        {
            header.FlagEncData.a[i] = gConstCipherFlagBuffer.a[i];
        }

        seal.seal_encrypt(sc, header.FlagEncData, dwRetVal, 0x00);

        //写入版本号
        header.VersionNumber = 0x3863911;

        //写入相关的时间信息
        header.BuildTime = new Timestamp(System.currentTimeMillis());
        header.LastUpdateTime = new Timestamp(System.currentTimeMillis());

        //加密算法
        header.CryptoInfo = new FILE_CRYPTO_INFO();
        header.CryptoInfo.CryptoID = 301;

        //密钥
        /**
         * 这个密钥需要重做，位置在D5-F2，也就是header.a[213]到header.a[242]，共计30位
         *
         */
        byte[] key="com.yangtusoft".getBytes();
        header.rightHead=new YT_FILE_RIGHT_HEAD();
        for (int i=0;i<header.rightHead.cFileEncKeyBuf.a.length;i++)
        {
            try
            {
                header.rightHead.cFileEncKeyBuf.a[i]=key[i];
            }
            catch(Exception e)
            {
                break;
            }
        }

        return header;
    }

    public static bytearray getHeader(PCIPHER_HEADER pheader)
    {
        Seal seal = new Seal();
        Seal.seal_ctx sc = seal.new seal_ctx();
        bytearray result = seal.new bytearray(CIPHER_HEDER_SIZE);

        /**
         * 按照顺序依次输出
         * MainFlag
         * FlagEndData
         * Encrypted
         * VersionNumber
         * BuildTime
         * LastUpdateTime
         * FILE_CRYPTO_INFO
         * YT_FILE_RIGHT_HEAD
         * Pading
         *
         * ----------！----------！注意！----------！----------
         * 所有对bytearray的操作绝对不能使用String类型！！！！！！
         */

        //定义一个偏移量，每次往结果中写入字节时，偏移量都会变化
        int OFFSET = 0;

        //1.输出MainFlag，其为bytearray类型，长度为32位
        byte[] temp_MainFlag = pheader.MainFlag.a;
        for (int i = 0; i < temp_MainFlag.length; i++, OFFSET++)
        {
            result.a[OFFSET] = temp_MainFlag[i];
        }
        System.out.println(OFFSET);


        //2.输出FlagEndData，为bytearray类型，是MainFlag的加密版，长度也为32位
        byte[] temp_FlagEncData = pheader.FlagEncData.a;
        for (int i = 0; i < temp_FlagEncData.length; i++, OFFSET++)
        {
            result.a[OFFSET] = temp_FlagEncData[i];
        }
        System.out.println(OFFSET);


        /**
         * 注意！
         * 40-D4，输出固定的值
         * 保持与客户端加密一致
         */
        byte [] unknown=new byte[]
        {
                0x00,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53, (byte) 0xAC, (byte) 0x97, (byte) 0xA3,0x01,0x00,0x00,
                0x00,0x00,0x00,0x00,0x00, (byte) 0xD1,0x63, (byte) 0xFC,0x0B,0x05,0x00,0x00,0x00,0x00,0x00,0x00,
                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                0x00,0x00,0x00,0x00,0x00
        };
        for (int i = 0; i < unknown.length; i++, OFFSET++)
        {
            result.a[OFFSET] = unknown[i];
        }
        System.out.println(OFFSET);

        //3.输出Encrypted，是一个char，不知道作用是什么

        //4.输出VersionNumber，这个我就不动了，保持了C++版一样的数字
        //byte[] temp_VersionNumber=intToByteArray(pheader.VersionNumber);
        //目前int转byte[]存在问题，先省略

        //5.BuildTime

        //6.LastUpdateTime

        //7.FILE_CRYPTO_INFO

        //8.YT_FILE_RIGHT_HEAD
        /**
         * 注意！
         * [213]-[242]位，填写密钥，共计最多30位
         */
        OFFSET=213;
        byte[] temp_YT_FILE_RIGHT_HEAD=pheader.rightHead.cFileEncKeyBuf.a;
        for (int i = 0; i < temp_YT_FILE_RIGHT_HEAD.length; i++, OFFSET++)
        {
            result.a[OFFSET] = temp_YT_FILE_RIGHT_HEAD[i];
        }
        System.out.println(OFFSET);

        return result;
    }

    public static void main(String[] args) throws Exception
    {
        Header hhh = new Header();
        hhh.BuildCipherHeader();

        OutputStream fos = new FileOutputStream("d:\\test4.txt");
        BufferedOutputStream bos = new BufferedOutputStream(fos, BUFFER_SIZE);
        bos.write(hhh.getHeader(hhh.header).a);
        bos.close();


    }


}
